package agh.sr.lab4.bank.client;

import java.io.FileNotFoundException;
import java.io.IOException;

import Bank.BankAccountPrx;
import Bank.BankAccountPrxHelper;
import Bank.BankManagerPrx;
import Bank.BankManagerPrxHelper;
import agh.sr.lab4.common.utils.ClientUtils;
import agh.sr.lab4.common.utils.Config;

public class BankClient {
	private int status = 0;
	private Ice.Communicator ic = null;
	private BankManagerPrx bankManagerProxy = null;
	private String serverConnectionString = null;

	private String pesel = "";

	public static void main(String[] args) {
		BankClient bankClient = new BankClient();
		try {
			bankClient.init(args);
			bankClient.mainLoop();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	private void init(String[] args) throws FileNotFoundException, IOException {
		String serverName = "CommonServer.Proxy";
		ic = Ice.Util.initialize(args);
		Ice.ObjectPrx base = ic.propertyToProxy(serverName);

		bankManagerProxy = BankManagerPrxHelper.checkedCast(base);
		if (bankManagerProxy == null)
			throw new Error("Invalid proxy");

		// extract connection info from properties
		serverConnectionString = new ClientUtils()
				.extractConnectionInfoFromProperty(args, serverName);

		System.out.println("SERVER: " + serverConnectionString);
	}

	private void mainLoop() {
		try {
			String line = null;
			java.io.BufferedReader in = new java.io.BufferedReader(
					new java.io.InputStreamReader(System.in));
			do {
				try {
					printMainLoopOptions();
					System.out.print("==> ");
					System.out.flush();
					line = in.readLine();
					if (line == null) {
						break;
					}
					if (line.equals("c") || line.equals("create")) {
						handleCreateAccount();
					} else if (line.equals("l") || line.equals("login")) {
						handleLogin();
					} else if (line.equals("t") || line.equals("test")) {
						handleTest();
					}
				} catch (Ice.ObjectNotExistException ex) {
					System.err.println("Account NOT exist");
				} catch (java.io.IOException ex) {
					System.err.println(ex);
				}
			} while ((!line.equals("q") && (!line.equals("quit"))));

		} catch (Ice.LocalException e) {
			e.printStackTrace();
			status = 1;
		} catch (Exception e) {
			System.err.println(e.getMessage());
			status = 1;
		}
		if (ic != null) {
			// Clean up
			try {
				ic.destroy();
			} catch (Exception e) {
				System.err.println(e.getMessage());
				status = 1;
			}
		}
		System.exit(status);

	}

	private void handleTest() {
		System.out.println("n TEST");
		String string = "BankAccountServant/asdds" + serverConnectionString;
		System.out.println(string);
		Ice.ObjectPrx base = ic.stringToProxy(string);

		BankAccountPrx bankAccountPrx = BankAccountPrxHelper.checkedCast(base);
		if (bankAccountPrx == null)
			throw new Error("Invalid proxy");
		bankAccountPrx.login("isndjv");

	}

	private void accountLoop(BankAccountPrx bankAccountProxy) {
		try {
			String line = null;
			java.io.BufferedReader in = new java.io.BufferedReader(
					new java.io.InputStreamReader(System.in));
			do {
				try {
					printAccountLoopOptions();
					System.out.print("====> ");
					System.out.flush();
					line = in.readLine();
					if (line == null) {
						break;
					}
					if (line.equals("b") || line.equals("getBalance")) {
						handleGetBalance(bankAccountProxy);
					} else if (line.equals("w") || line.equals("withdraw")) {
						handleWithdraw(bankAccountProxy);
					} else if (line.equals("s") || line.equals("supply")) {
						handleSupply(bankAccountProxy);
					} else if (line.equals("o") || line.equals("logoff")) {
						handleLogOff(bankAccountProxy);
					}
				} catch (java.io.IOException ex) {
					System.err.println(ex);
				}
			} while ((!line.equals("o") && (!line.equals("logoff"))));

		} catch (Ice.LocalException e) {
			e.printStackTrace();
		} catch (Exception e) {
			System.err.println(e.getMessage());
		}

	}

	private void printMainLoopOptions() {
		System.out.println("+++ BANK MANAGER - Main Menu, not logged +++");
		System.out.println("+++ options: login(l), create(c), quit(q)");
	}

	private void printAccountLoopOptions() {
		System.out.println("--- BANK MANAGER -Manage Account, logged in as: "
				+ pesel);
		System.out
				.println("--- options: getBalance(b), withdraw(w), supply(s), logoff(o)");
	}

	private void handleCreateAccount() throws IOException {
		String pesel = readPesel();
		bankManagerProxy.createAccount(pesel);
		printInfo("Account created: " + pesel);
	}

	private void handleLogin() throws IOException {
		pesel = readPesel();
		String proxyString = Config.BANK_CATEGORY + "/" + pesel
				+ serverConnectionString;
		System.out.println(proxyString);
		Ice.ObjectPrx base = ic.stringToProxy(proxyString);

		// BankAccountPrx bankAccountPrx =
		// BankAccountPrxHelper.checkedCast(base);
		BankAccountPrx bankAccountPrx = BankAccountPrxHelper
				.uncheckedCast(base);
		if (bankAccountPrx == null)
			throw new Error("Invalid proxy");
		bankAccountPrx.login(pesel);
		accountLoop(bankAccountPrx);
	}

	private void handleLogOff(BankAccountPrx bankAccountProxy) {
		// Map<String, String> _ctx = new HashMap<String, String>();
		// _ctx.put(Config.PESEL, pesel);
		// bankAccountProxy.logoff(_ctx);
		bankAccountProxy.logoff();
		pesel = null;
		printInfo("Logged Off");
	}

	private void handleSupply(BankAccountPrx bankAccountProxy)
			throws IOException {
		double amount = readAmount();

		// Map<String, String> _ctx = new HashMap<String, String>();
		// _ctx.put(Config.PESEL, pesel);
		// bankAccountProxy.supply(amount, _ctx);

		bankAccountProxy.supply(amount);

		printInfo("account supplied: " + amount);
	}

	private void handleWithdraw(BankAccountPrx bankAccountProxy)
			throws IOException {
		double amount = readAmount();

		// Map<String, String> _ctx = new HashMap<String, String>();
		// _ctx.put(Config.PESEL, pesel);
		// bankAccountProxy.withdraw(amount, _ctx);
		bankAccountProxy.withdraw(amount);
		printInfo("Account withdrew: " + amount);
	}

	private void handleGetBalance(BankAccountPrx bankAccountProxy) {
		// Map<String, String> _ctx = new HashMap<String, String>();
		// _ctx.put(Config.PESEL, pesel);
		// double balance = bankAccountProxy.getBalance(_ctx);
		double balance = bankAccountProxy.getBalance();
		printInfo("Account balance: " + balance);
	}

	private void printInfo(String msg) {
		System.out.println(">>> " + msg);
	}

	private double readAmount() throws IOException {
		double _amount = 0;

		java.io.BufferedReader in = new java.io.BufferedReader(
				new java.io.InputStreamReader(System.in));
		do {
			System.out.println("Type amount:");
			try {
				_amount = Double.valueOf(in.readLine());
			} catch (NumberFormatException e) {
				System.out.println("invalid value, must bu greater than 0");
			}
		} while (_amount <= 0);

		return _amount;
	}

	private String readPesel() throws IOException {
		String _pesel = "";
		java.io.BufferedReader in = new java.io.BufferedReader(
				new java.io.InputStreamReader(System.in));
		do {
			System.out.println("Type valid pesel:");
			_pesel = in.readLine();
		} while (!_pesel.matches("[0-9]{1,11}"));

		return _pesel;
	}

}
